package com.jiangjiang.eshop.auth.facade;

import com.jiangjiang.eshop.auth.cache.PriorityCacheManager;
import com.jiangjiang.eshop.auth.convert.PriorityConvert;
import com.jiangjiang.eshop.auth.dao.PriorityMapper;
import com.jiangjiang.eshop.auth.dto.PriorityDTO;
import com.jiangjiang.eshop.auth.dto.PriorityNode;
import com.jiangjiang.eshop.auth.dto.PrioritySaveDTO;
import com.jiangjiang.eshop.auth.dto.PriorityUpdateDTO;
import com.jiangjiang.eshop.auth.domain.PriorityEntity;
import com.jiangjiang.eshop.auth.operation.QueryAuthorizedPriorityOperation;
import com.jiangjiang.eshop.auth.service.AccountPriorityRelationShipService;
import com.jiangjiang.eshop.auth.service.PriorityService;
import com.jiangjiang.eshop.auth.service.RolePriorityRelationShipService;
import com.jiangjiang.eshop.auth.operation.PriorityNodeRelateCheckOperation;
import com.jiangjiang.eshop.auth.operation.PriorityNodeRemoveOperation;
import com.jiangjiang.eshop.common.bean.SpringApplicationContext;
import com.jiangjiang.eshop.common.help.DateHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName PriorityFacade
 * @Description TODO
 * @Author jhw
 * @Date 2021/4/27 21:22
 * @Version 1.0
 **/
@Slf4j
@Component
public class PriorityFacade {
    @Autowired
    private PriorityService priorityService;
    @Autowired
    private PriorityConvert priorityConvert;
    @Autowired
    private DateHelper dateHelper;
    @Autowired
    private SpringApplicationContext context;
    @Autowired
    private PriorityCacheManager priorityCacheManager;
    /**
     * 查询所有的根权限
     *
     * @return
     */
    public List<PriorityDTO> listRootPriorities() {
        return priorityConvert.convertEntities2DTOList(priorityService.listRootPriorities());
    }

    /**
     * 查询父级权限关联的子权限
     *
     * @param parentId 父级权限id
     * @return
     */
    public List<PriorityDTO> listChildrenPriorities(Long parentId) {
        return priorityConvert.convertEntities2DTOList(priorityService.listChildrenPriorities(parentId));
    }

    /**
     * 保存权限
     *
     * @param priorityDTO
     * @return
     */
    public Boolean save(PrioritySaveDTO priorityDTO) throws ParseException {
        Date currentDate = dateHelper.getCurrentDate();
        PriorityEntity entity = priorityConvert.prioritySaveDtoConvert2Entity(priorityDTO);
        entity.setGmtCreate(currentDate);
        entity.setGmtModified(currentDate);
        return priorityService.save(entity);
    }

    /**
     * 更新权限
     *
     * @param priorityDTO
     * @return
     */
    public Boolean update(PriorityUpdateDTO priorityDTO) {
        PriorityEntity entity = priorityService.queryById(priorityDTO.getId());
        entity.setCode(priorityDTO.getCode());
        entity.setParentId(priorityDTO.getParentId());
        entity.setPriorityComment(priorityDTO.getPriorityComment());
        entity.setPriorityType(priorityDTO.getPriorityType());
        entity.setUrl(priorityDTO.getUrl());

        Boolean result = priorityService.updateById(entity);
        if(result){
            // 清空所有与之绑定账号的缓存
           List<Long> accountIds =  priorityService.listAccountIdsByPriorityId(priorityDTO.getId());
            for (Long accountId : accountIds) {
                priorityCacheManager.removeCache(accountId);
            }

        }

        return result;
    }

    /**
     * 根据id查询权限
     *
     * @param id 权限id
     * @return
     */
    public PriorityDTO queryById(Long id) {
        PriorityEntity entity = priorityService.queryById(id);
        return priorityConvert.convertEntities2DTO(entity);
    }

    /**
     * 删除权限
     *
     * @param id 权限id
     */
    public Boolean removePriority(Long id) throws Exception {
        PriorityEntity entity = priorityService.queryById(id);
        PriorityNode priorityNode = new PriorityNode();
        BeanUtils.copyProperties(entity, priorityNode);

        PriorityNodeRelateCheckOperation relateCheckOperation = context.getBean(PriorityNodeRelateCheckOperation.class);
        Boolean result = priorityNode.execute(relateCheckOperation);
        if (result) {
            return false;
        }

        PriorityNodeRemoveOperation removeOperation = context.getBean(PriorityNodeRemoveOperation.class);
        return priorityNode.execute(removeOperation);
    }

    /**
     * 根据用户账号查询权限数据
     *
     * @param accountId 用户账号id
     * @return 查询结果
     */
    public List<PriorityNode> listAuthorizedTreeByAccountId(Long accountId) throws Exception {
        List<PriorityNode> priorityTree = priorityCacheManager.getPriorityTree(accountId);
        if(!CollectionUtils.isEmpty(priorityTree)){
            return priorityTree;
        }

        List<PriorityEntity> priorityEntities = priorityService.listAuthorizedTreeByAccountId(accountId, null);
        QueryAuthorizedPriorityOperation operation = context.getBean(
                QueryAuthorizedPriorityOperation.class);
        operation.setAccountId(accountId);
        List<PriorityNode> authorizedTree = new ArrayList<>();
        for (PriorityEntity entity : priorityEntities) {
            PriorityNode node = new PriorityNode();
            BeanUtils.copyProperties(entity, node);
            node.execute(operation);
            authorizedTree.add(node);
        }

        priorityCacheManager.setPriorityTree(accountId, authorizedTree);

        return authorizedTree;
    }

    /**
     * 判断账号是否存在对指定url的权限的授权记录
     *
     * @param accountId 账号id
     * @param url       权限url
     * @return 是否存在授权记录
     */
    public Boolean existAuthorizedByUrl(Long accountId, String url) {
        Boolean result = priorityCacheManager.getPriorityUrlCache(accountId,url);
        if(result != null){
            return result;
        }
        result = priorityService.countAuthorizedByUrl(accountId, url) > 0;

        priorityCacheManager.setPriorityUrlCache(accountId,url,result);
        return result;
    }

    /**
     * 判断账号是否存在对指定编号的权限的授权记录
     *
     * @param accountId 账号id
     * @param code       权限url
     * @return 是否存在授权记录
     */
    public Boolean existAuthorizedByCode(Long accountId, String code) {
        Boolean result = priorityCacheManager.getPriorityCodeCache(accountId,code);
        if(result != null){
            return result;
        }

        result =priorityService.existAuthorizedByCode(accountId, code) > 0;
        priorityCacheManager.setPriorityCodeCache(accountId,code,result);
        return result;
    }
}
